const WebSocket = require('ws')
const jwt = require('jsonwebtoken')
//创建对象，监听3000端口
const wss = new WebSocket.Server({ port: 3000 })
//let num = 0 //实时在线人数
let group = {} //房间在线人数
const timeInterval = 1000//心跳频率
//监听新的连接
wss.on('connection', function connection (ws) {
  // 初始化心跳连接状态
  ws.isAlive = true
  // ws指客户端
  ws.on('message', function (msg) {
    //绑定name属性、roomid属性
    const msgObj = JSON.parse(msg)
    if (msgObj.event === 'enter') {
      ws.name = msgObj.message//用户昵称
      ws.roomid = msgObj.roomid//房间号
      if (typeof group[ws.roomid] === 'undefined') {
        group[ws.roomid] = 1
      } else {
        group[ws.roomid]++
      }
      // num++
    }
    if (msgObj.event === 'auth') {
      jwt.verify(msgObj.message, 'secret', (err, decode) => {
        if (err) {
          console.log('auth error');
          ws.send(JSON.stringify({
            event: 'noauth',
            message: 'please auth again'
          }))
          return
        } else {
          //鉴权通过
          console.log(decode);
          ws.isAuth = true
          return
        }
      })
      return
    }
    //拦截非鉴权请求
    if (!ws.isAuth) {
      return
    }
    //心跳检测
    if (msgObj.event === 'heartbeat' && msgObj.message === 'pong') {
      ws.isAlive = true
      return
    }
    //消息广播
    wss.clients.forEach((client) => {
      // client.roomid === ws.roomid ->实现相同id才进行消息广播
      if (client.readyState === WebSocket.OPEN && client.roomid === ws.roomid) {
        msgObj.name = ws.name
        msgObj.num = group[ws.roomid] //在线人数 num
        client.send(JSON.stringify(msgObj))
      }
    })
  })
  //当ws关闭的时候
  ws.on('close', function () {
    if (ws.name) {
      group[ws.roomid]--
    }
    let msgObj = {}
    wss.clients.forEach((client) => {
      //ws.roomid === client.roomid ->只有在当前房间才去广播退出消息
      if (client.readyState === WebSocket.OPEN && ws.roomid === client.roomid) {
        msgObj.name = ws.name
        msgObj.num = group[ws.roomid] //在线人数
        msgObj.event = 'out'
        client.send(JSON.stringify(msgObj))
      }
    })
  })
})
setInterval(() => {
  wss.clients.forEach((ws) => {
    if (!ws.isAlive && ws.roomid) {
      group[ws.roomid]--
      delete ws['roomid']
      return ws.terminate()//关闭ws连接的方法
    }
    //主动发送心跳检测
    //当客户端返回消息之后，主动设置flag为在线
    ws.isAlive = false
    ws.send(JSON.stringify({
      event: 'heartbeat',
      message: 'ping',
      num: group[ws.roomid]
    }))
  })
}, timeInterval)

